package com.comunity_cloud.client.model.fetch_file;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

import com.comunity_cloud.client.model.Configuration;
import com.comunity_cloud.client.model.MainModel2;
import com.comunity_cloud.client.model.communication.ConnectionsManager;
import com.comunity_cloud.client.model.communication.PacketListener;
import com.comunity_cloud.client.model.communication.PeerConnection;
import com.comunity_cloud.client.model.communication.packet.PeerPacket;
import com.comunity_cloud.client.model.communication.packet.PeerPacketHeader.Type;
import com.comunity_cloud.client.model.upload_file.FileChunkHeader;
import com.user_hosted_storage.dto.CommunityDTO;

public class FetchFilesServer extends Thread implements PacketListener<FetchFileHeader> {

	private BlockingQueue<PeerPacket<FetchFileHeader>> requests = new LinkedBlockingDeque<>();
	
	public FetchFilesServer() {
		PeerConnection.addPacketListener(Type.FETCH_FILE, this);
		start();
	}
	
	@Override
	public void run() {
		
		FileInputStream fileInputStream = null;
		
		while(true) {
			try {
				PeerPacket<FetchFileHeader> packet = requests.take();
				PeerConnection peerConnection = ConnectionsManager.getInstance().getPeerConnection(packet.getClientId());
				FetchFileHeader header = packet.getHeader();
				String fileName = header.getFileName();
				CommunityDTO community = MainModel2.getInstance().getCommunity(header.getCommunityId());
				
				fileInputStream = new FileInputStream(Configuration.getInstance().hostedFilesPath+community.getName()+File.separator+fileName);
				
				byte[] fileChunkHeaderBytes = new byte[FileChunkHeader.SIZE];
				
				fileInputStream.read(fileChunkHeaderBytes);
				
				FileChunkHeader fileChunkHeader = new FileChunkHeader();
				fileChunkHeader.fromBytes(fileChunkHeaderBytes);
				
				FetchFileResponse fetchFileResponse = new FetchFileResponse();
				
				fetchFileResponse.setFileName(fileName);
				fetchFileResponse.setCommunityId(community.getId());
				
				byte[] payloadBuffer = new byte[Configuration.getInstance().readBufferSize];
				
				long totalBytesRead = 0;
				
				PeerPacket<FetchFileResponse> peerPacket = new PeerPacket<>(fetchFileResponse,payloadBuffer);
				
				while(true) {
					int bytesRead = fileInputStream.read(payloadBuffer);
					
					fetchFileResponse.setOffset(totalBytesRead+fileChunkHeader.getTotalOffset());
					
					totalBytesRead += bytesRead;
					
					fetchFileResponse.setPayloadSize(bytesRead);
					
					peerConnection.sendPacket(peerPacket);
				}
				
			} catch (InterruptedException e) {
			
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					if (fileInputStream != null) {
						fileInputStream.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	@Override
	public void packetReceived(PeerPacket<FetchFileHeader> peerPacket) {
		requests.add(peerPacket);
	}

}
